/**
 * Copyright 2018 orivil.com. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package wechat

import (
	"hash"
	"github.com/google/go-querystring/query"
	"sort"
	"strings"
	"encoding/hex"
)

// 将结构体转换为签名，结构体字段可以使用 url 标签进行重命名
// 获得 md5 签名：getSign(schema, md5.New(), ""), 微信还规定要将结果转换为大写
// 获得 sha1 签名：getSign(schema, sha1.New(), "")
// key 可为空, 通常为商户平台的签名需要设置为 ShopKey 值
func GetSign(schema interface{}, mod hash.Hash, key string) (sign string, err error) {
	vs, e := query.Values(schema)
	if e != nil {
		return "", e
	}
	//STEP 1: 对key进行升序排序，略过空值
	var keys []string
	for key, vues := range vs {
		if len(vues) > 0 && vues[0] != "" && vues[0] != "0" {
			keys = append(keys, key)
		}
	}
	sort.Strings(keys)

	//STEP2: 对key=value的键值对用&连接起来
	var kv string
	for _, k := range keys {
		kv += k + "=" + vs[k][0] + "&"
	}

	//STEP3, 在键值对的最后加上key=API_KEY
	if key != "" {
		kv += "key=" + key
	} else {
		kv = strings.TrimSuffix(kv, "&")
	}
	//STEP4：hash 序列化，可以为 MD5 或 SHA1，如果是 MD5 需要将结果转换为大写
	mod.Write([]byte(kv))
	cipherStr := mod.Sum(nil)
	return strings.ToUpper(hex.EncodeToString(cipherStr)), nil
}
